package com.cd.university.service.impl;

import com.cd.university.common.RestResult;
import com.cd.university.common.UniversityConstants;
import com.cd.university.common.utils.SpringUtil;
import com.cd.university.db.mapper.PatentExamineMapper;
import com.cd.university.db.mapper.PatentMapper;
import com.cd.university.db.pojo.Message;
import com.cd.university.db.pojo.Patent;
import com.cd.university.db.pojo.PatentExamine;
import com.cd.university.service.MessageService;
import com.cd.university.service.abs.AbstractAchievementProcessor;
import com.cd.university.vo.PatentExamineVo;
import com.cd.university.vo.ProjectExamineVo;
import com.cd.university.vo.UserVo;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronizationAdapter;
import org.springframework.transaction.support.TransactionSynchronizationManager;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author 陈栋
 * @create 2021/11/3 16:50
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class PatentProcessor extends AbstractAchievementProcessor<Patent, PatentExamineVo> {

    @Autowired
    private PatentMapper patentMapper;

    private ObjectMapper objectMapper = new ObjectMapper();

    @Autowired
    private PatentExamineMapper patentExamineMapper;

    @Autowired
    private MessageService messageService;

    @Override
    protected void saveMessage(PatentExamineVo examineVo) {
        ProjectExamineVo vo = searchPEVoByProjectId(examineVo.getProjectId());
        messageService.submitFinalApplication(new Message(examineVo.getProjectId(),
                vo.getProjectName(),
                examineVo.getReviewerId(),
                UniversityConstants.PROJECT_ACHIEVEMENT_PATENT,
                examineVo.getPtId(),
                UniversityConstants.MESSAGE_STATUS_FINAL_APPLICATION));
    }

    @Override
    public Patent insertData(Object data) {
        // 将Object转成Patent对象
        Patent patent = objectMapper.convertValue(data, Patent.class);

        ProjectExamineVo projectExamineVo = super.searchPEVoByProjectId(patent.getProjectId());
        if (!projectExamineVo.getStatusId().equals(UniversityConstants.PROJECT_STATUS_SECOND_PASS)){
            return null;
        }

        // 插入数据
        int row = patentMapper.insert(patent);

        if (row < 1) {
            throw new RuntimeException("专利上传失败,数据错误");
        }

        if (!updateDbStatus(UniversityConstants.PROJECT_STATUS_SUCCESS_PROJECT, projectExamineVo.getProjectName())) {
            throw new RuntimeException("更新数据库失败");
        }

        PaperProcessor bean = SpringUtil.getBean(PaperProcessor.class);
        bean.updateRedisStatus(patent.getProjectId(),UniversityConstants.PROJECT_STATUS_SUCCESS_PROJECT, patent.getPatentId());
        return patent;
    }

    @Override
    public PatentExamineVo generateVo(Patent data) {
        // 创建一个PaperExamineVo对象
        PatentExamineVo examineVo = new PatentExamineVo();
        BeanUtils.copyProperties(data,examineVo);
        examineVo.setExamineStatus("未审核");

        // 因为PaperExamineVo对象中有projectExamineVo对象，所以需要把projectExamineVo对象找到，根据projectId查找
        Integer projectId = data.getProjectId();
        ProjectExamineVo projectExamineVo = super.searchPEVoByProjectId(projectId);

        // 搜索负责人
        for (UserVo userVo : projectExamineVo.getTeam()) {
            if (userVo.getUserId().equals(data.getLeaderId())) {
                examineVo.setLeaderName(userVo.getUserRealname());
                break;
            }
        }

        // 向数据库中插入审核
        PatentExamine pojo = new PatentExamine();
        BeanUtils.copyProperties(examineVo,pojo);
        int row = patentExamineMapper.insertSelective(pojo);
        if (row < 1) {
            throw new RuntimeException("插入论文审核失败");
        }

        // 设置普通成员变量
        examineVo.setProjectExamineVo(projectExamineVo);
        examineVo.setPeId(pojo.getPeId());
        return examineVo;
    }

    @Override
    public List<PatentExamineVo> passedResults(List<PatentExamineVo> list) {
        ArrayList<PatentExamineVo> result = new ArrayList<>();
        for (PatentExamineVo examineVo : list) {
            if (!examineVo.getExamineStatus().equals("未审核")) {
                result.add(examineVo);
            }
        }
        return result;
    }

    @Override
    public void loadToRedis() {
        ValueOperations opsForValue = redisTemplate.opsForValue();
        List<PatentExamine> patentExamines = patentExamineMapper.searchAll();

        List<PatentExamineVo> patentExamineVos = new ArrayList<>();
        for (PatentExamine patentExamine : patentExamines) {
            PatentExamineVo vo = new PatentExamineVo();
            BeanUtils.copyProperties(patentExamine, vo);

            ProjectExamineVo projectExamineVo = searchPEVoByProjectId(patentExamine.getProjectId());
            vo.setProjectExamineVo(projectExamineVo);

            // 设置负责人姓名
            for (UserVo userVo : projectExamineVo.getTeam()) {
                if (userVo.getUserId().equals(patentExamine.getLeaderId())) {
                    vo.setLeaderName(userVo.getUserRealname());
                    break;
                }
            }
            // 设置申请时间
            vo.setApplyTime(patentExamine.getApplyTime());

            patentExamineVos.add(vo);
        }

        // 先删除Redis中的缓存
        redisTemplate.delete(repositoryName.get(getThisClassName()));
        // 放入到redis中
        opsForValue.set(repositoryName.get(getThisClassName()), patentExamineVos);
    }

    @Override
    public List<PatentExamineVo> searchExamineByName(String name) {
        List<PatentExamineVo> list = getValueFromRedis(getThisClassName());

        List<PatentExamineVo> result = new ArrayList<>();
        for (PatentExamineVo patentExamineVo : list) {
            if (patentExamineVo.getPatentName().contains(name)) {
                result.add(patentExamineVo);
            }
        }
        return result;
    }

    @Override
    public List<PatentExamineVo> searchByUserName(List<PatentExamineVo> list, String userName) {
        List<PatentExamineVo> result = new ArrayList<>();

        for (PatentExamineVo patentExamineVo : list) {
            if (patentExamineVo.getLeaderName()!=null && patentExamineVo.getLeaderName().contains(userName)) {
                result.add(patentExamineVo);
            }
        }
        return result;
    }

    @Override
    public RestResult approvedAchievement(Integer peId, Integer reviewerId) {
        PatentExamine examine = new PatentExamine();
        examine.setExamineStatus("审核通过");
        examine.setPeId(peId);
        examine.setReviewerId(reviewerId);
        examine.setApplyTime(new Date(System.currentTimeMillis()));

        PatentExamine patentExamine = patentExamineMapper.selectByPrimaryKey(peId);
        patentExamine.setPatentId(patentExamine.getPatentId());
        if (patentExamine==null) {
            return RestResult.failure("论文的审核id有误，请重新检查");
        }

        Integer projectId = patentExamine.getProjectId();
        ProjectExamineVo projectExamineVo = searchPEVoByProjectId(projectId);

        // 更新数据库中的项目文件的状态,项目文件通过审核则为
        boolean dbProjectFileStatus = updateDbProjectFileStatus(projectId, UniversityConstants.PROJECT_FILE_PASS, patentExamine.getPatentId());
        if (!dbProjectFileStatus) {
            return RestResult.failure("项目文件审核失败");
        }

        boolean status = updateDbStatus(UniversityConstants.PROJECT_STATUS_FINALIZE_PROJECT, projectExamineVo.getProjectName());
        if (!status) {
            return RestResult.failure("更新项目以及项目审核状态失败");
        }


        int row = patentExamineMapper.updateByPrimaryKeySelective(examine);
        if (row < 1) {
            throw  new RuntimeException("审核专利失败，请重试");
        }

        // 直接调用loadToRedis更新Redis
        PatentProcessor bean = SpringUtil.getBean(PatentProcessor.class);

        if (TransactionSynchronizationManager.isActualTransactionActive()) {
            //存在事物，则注册事务同步处理
            TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
                @Override
                public void afterCommit() {
                    loadToRedis();
                    // 更新Redis中的项目、项目文件、项目审核中的内容
                    bean.updateRedisStatus(patentExamine.getProjectId(),UniversityConstants.PROJECT_STATUS_FINALIZE_PROJECT,patentExamine.getPatentId());
                }
            });
        }

        bean.approveSaveMessage(projectId,
                projectExamineVo.getProjectName(),
                reviewerId,
                UniversityConstants.PROJECT_ACHIEVEMENT_AWARD,
                patentExamine.getPtId());

        return RestResult.success("审核专利成功");
    }
}
